Skip to content

登录后弹窗 ​

本节目标:理解“登录后弹窗”的核心思路,并能把它用于实际开发或面试表达。 好嘞—按你“只给需要调整的片段、且复杂逻辑在上一行注释”的要求,下面是把 (public)/layout.vue 里“手机号验证弹窗”相关逻辑精简/强化后的替换片段。照着替换即可,其他不动。


1) 在** \<template\> 里加入弹窗组件挂载点** ​

> 放在 \<a-layout\> 的最后比较稳:不影响侧栏/头部的层级。

vue
<!-- 复杂逻辑:手机号验证弹窗(受 query: phone_verify=0 控制;组件内部不改路由) -->
<PhoneVerifyModal
  v-model:open="phoneVerifyVisible"
  @success="onPhoneVerifySuccess"
  @close="onPhoneVerifyClose"
/>

> 插入位置建议:你已有的 \<router-view /\> 下方、\</a-layout\> 之前。 ​

2) 在 \<script setup\> 顶部 增加 import ​

> 如果你的弹窗组件路径不同,改成自己的路径即可。

ts
// 复杂逻辑:引入手机号验证弹窗组件
import PhoneVerifyModal from '@/components/phone-verify/PhoneVerifyModal.vue'

3) 替换弹窗显隐与回调逻辑(把你现有这几段替换掉) ​

> 替换你原先的 phoneVerifyVisible 的 watch / success / close 三段。

ts
// 复杂逻辑:是否需要触发验证弹窗(登录 + 未验证 + URL 显式标记)
const needPhoneVerify = computed(() => {
  return (
    userStore.isLoggedIn &&
    userStore.userInfo?.phone_verify === false &&
    route.query.phone_verify === '0'
  )
})
// 复杂逻辑:弹窗显隐状态(仅由 needPhoneVerify 驱动;避免多处状态源)
const phoneVerifyVisible = ref(false)
// 复杂逻辑:根据路由与用户信息的变更,自动控制弹窗显隐
watch(
  needPhoneVerify,
  (flag) => {
    phoneVerifyVisible.value = flag
  },
  { immediate: true },
)
// 复杂逻辑:清除 URL 指定的某个查询参数(保持当前路由名/参数,其它查询不变)
const clearQueryKey = (key: string) => {
  const { [key]: _drop, ...rest } = route.query
  router.replace({ name: String(route.name || ''), params: route.params, query: rest })
}
// 复杂逻辑:验证成功 -> 更新本地用户信息 + 清理 URL 标记(下次不再弹)
const onPhoneVerifySuccess = () => {
  userStore.setUserInfo({ phone_verify: true })
  clearQueryKey('phone_verify')
  phoneVerifyVisible.value = false
}
// 复杂逻辑:用户手动关闭 -> 仅关闭 UI,不清 URL 标记(下次进入仍会提示)
const onPhoneVerifyClose = () => {
  phoneVerifyVisible.value = false
}

> 这段把显隐的单一真相收敛到 needPhoneVerify,避免“多个 watch 源”导致的闪烁/不同步。 ​

4) (可选强化)防抖防止频繁闪烁(网络慢时重复开关) ​

> 如果你遇到用户信息延迟更新导致弹窗闪一下,再加一个微小防抖即可。

ts
// 复杂逻辑:微防抖,避免极短时间内反复开关导致闪烁
let toggleTimer: number | null = null
watch(needPhoneVerify, (flag) => {
  if (toggleTimer) window.clearTimeout(toggleTimer)
  toggleTimer = window.setTimeout(() => {
    phoneVerifyVisible.value = flag
    toggleTimer = null
  }, 50)
})

> 有了这段,就把上面第 3 点 watch(needPhoneVerify, ...) 替换为这段即可(两者选其一)。 ​

5) 删除你原文件中这几处老逻辑(避免冲突) ​

  • const phoneVerifyVisible = ref(false) 保留(因上方也用了),但删除你原来的:
    • 对 route.query.phone_verify 的 watch(...);
    • 旧的 onPhoneVerifySuccess / onPhoneVerifyClose 实现;
  • 页面里其它无关逻辑(侧栏、抽屉、copy header 等)保持不动。

为什么这样改? ​

  • 入口统一:显示与否仅由 needPhoneVerify 决定(登录/未验证/URL 标记);
  • 可控回退:success 清 URL 标记并写回 userStore,确保下次不弹;
  • 用户可拒绝:close 不清 URL 标记,下次进入仍会提示(你的需求);
  • 避免状态打架:不再同时 watch(query) + watch(meta) 多源更新,减少竞态与闪烁;
  • 与我们在守卫里建议的 phone-verify beforeEach 完整配合(守卫会在满足条件时把 ?phone_verify=0 自动补上,页面只负责 UI)。

需要我顺手给一个**PhoneVerifyModal.vue 的极简参考外壳**吗?(如 v-model:open、@success、@close 的事件/prop 约定)如果你现有的组件接口不同,我也可以按你现有接口改上面片段。

本站总访问 — 次